// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2019-2022 Intel Corporation <www.intel.com>
 *
 */

#include <init.h>
#include <log.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/u-boot.h>
#include <asm/utils.h>
#include <common.h>
#include <hang.h>
#include <image.h>
#include <spl.h>
#include <asm/arch/clock_manager.h>
#include <asm/arch/firewall.h>
#include <asm/arch/mailbox_s10.h>
#include <asm/arch/misc.h>
#include <asm/arch/reset_manager.h>
#include <asm/arch/smmu_s10.h>
#include <asm/arch/system_manager.h>
#include <wdt.h>
#include <dm/uclass.h>

DECLARE_GLOBAL_DATA_PTR;

#define USE_HARDCODED_HANDOFF

#ifdef USE_HARDCODED_HANDOFF
static const u32 hardcoded_handoff_data[394] = {
        0x544f4f42, 0x01000500, 0x00000000, 0x00000000, 0x58554d50, 0x90010000,
        0x00000000, 0x00000000, 0x00000000, 0x03000000, 0x04000000, 0x03000000,
        0x08000000, 0x03000000, 0x0c000000, 0x03000000, 0x10000000, 0x03000000,
        0x14000000, 0x03000000, 0x18000000, 0x03000000, 0x1c000000, 0x03000000,
        0x20000000, 0x03000000, 0x24000000, 0x03000000, 0x28000000, 0x03000000,
        0x2c000000, 0x03000000, 0x30000000, 0x03000000, 0x34000000, 0x03000000,
        0x38000000, 0x03000000, 0x3c000000, 0x03000000, 0x40000000, 0x00000000,
        0x44000000, 0x00000000, 0x48000000, 0x00000000, 0x4c000000, 0x00000000,
        0x50000000, 0x00000000, 0x54000000, 0x00000000, 0x58000000, 0x04000000,
        0x5c000000, 0x04000000, 0x60000000, 0x08000000, 0x64000000, 0x08000000,
        0x68000000, 0x05000000, 0x6c000000, 0x05000000, 0x70000000, 0x08000000,
        0x74000000, 0x08000000, 0x78000000, 0x04000000, 0x7c000000, 0x04000000,
        0x80000000, 0x07000000, 0x84000000, 0x07000000, 0x88000000, 0x07000000,
        0x8c000000, 0x07000000, 0x90000000, 0x01000000, 0x94000000, 0x01000000,
        0x98000000, 0x01000000, 0x9c000000, 0x01000000, 0x00010000, 0x01000000,
        0x04010000, 0x01000000, 0x08010000, 0x09000000, 0x0c010000, 0x08000000,
        0x10010000, 0x08000000, 0x14010000, 0x08000000, 0x18010000, 0x05000000,
        0x1c010000, 0x05000000, 0x54434f49, 0x90010000, 0x00000000, 0x00000000,
        0x00000000, 0x34000000, 0x04000000, 0x14000000, 0x08000000, 0x34000000,
        0x0c000000, 0x34000000, 0x10000000, 0x34000000, 0x14000000, 0x34000000,
        0x18000000, 0x34000000, 0x1c000000, 0x34000000, 0x20000000, 0x34000000,
        0x24000000, 0x34000000, 0x28000000, 0x34000000, 0x2c000000, 0x34000000,
        0x30000000, 0x16000000, 0x34000000, 0x14000000, 0x38000000, 0x34000000,
        0x3c000000, 0x34000000, 0x40000000, 0x14000000, 0x44000000, 0x14000000,
        0x48000000, 0x34000000, 0x4c000000, 0x34000000, 0x50000000, 0x14000000,
        0x54000000, 0x14000000, 0x58000000, 0x34000000, 0x5c000000, 0x34000000,
        0x60000000, 0x35000000, 0x64000000, 0x35000000, 0x68000000, 0x16000000,
        0x6c000000, 0x34000000, 0xd0000000, 0x35000000, 0xd4000000, 0x35000000,
        0xd8000000, 0x3e000000, 0xdc000000, 0x3e000000, 0xe0000000, 0x34000000,
        0xe4000000, 0x34000000, 0xe8000000, 0x16000000, 0xec000000, 0x34000000,
        0xf0000000, 0x34000000, 0xf4000000, 0x34000000, 0xf8000000, 0x14000000,
        0xfc000000, 0x34000000, 0x00010000, 0x34000000, 0x04010000, 0x34000000,
        0x08010000, 0x34000000, 0x0c010000, 0x35000000, 0x10010000, 0x35000000,
        0x14010000, 0x35000000, 0x18010000, 0x3e000000, 0x1c010000, 0x16000000,
        0x41475046, 0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x04000000, 0x00000000, 0x08000000, 0x00000000, 0x0c000000, 0x00000000,
        0x10000000, 0x00000000, 0x14000000, 0x00000000, 0x18000000, 0x00000000,
        0x1c000000, 0x00000000, 0x20000000, 0x00000000, 0x28000000, 0x00000000,
        0x2c000000, 0x00000000, 0x30000000, 0x00000000, 0x34000000, 0x00000000,
#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU)
        0x38000000, 0x01000000, 0x3c000000, 0x00000000, 0x40000000, 0x00000000,
#else
        0x38000000, 0x00000000, 0x3c000000, 0x00000000, 0x40000000, 0x00000000,
#endif
        0x44000000, 0x00000000, 0x48000000, 0x00000000, 0x50000000, 0x00000000,
        0x54000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x59414c44, 0x90010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x04000000, 0x00000000, 0x08000000, 0x00000000, 0x0c000000, 0x00000000,
        0x10000000, 0x00000000, 0x14000000, 0x00000000, 0x18000000, 0x00000000,
        0x1c000000, 0x00000000, 0x20000000, 0x00000000, 0x24000000, 0x00000000,
        0x28000000, 0x00000000, 0x2c000000, 0x00000000, 0x30000000, 0x00110000,
        0x34000000, 0x00000000, 0x38000000, 0x00000000, 0x3c000000, 0x00000000,
        0x40000000, 0x00000000, 0x44000000, 0x00000000, 0x48000000, 0x00000000,
        0x4c000000, 0x00000000, 0x50000000, 0x00000000, 0x54000000, 0x00000000,
        0x58000000, 0x00000000, 0x5c000000, 0x00000000, 0x60000000, 0x00000000,
        0x64000000, 0x00000000, 0x68000000, 0x00000000, 0x6c000000, 0x00000000,
        0x70000000, 0x00000000, 0x74000000, 0x00000000, 0x78000000, 0x00000000,
        0x7c000000, 0x00000000, 0x80000000, 0x00000000, 0x84000000, 0x00000000,
        0x88000000, 0x00000000, 0x8c000000, 0x00000000, 0x90000000, 0x00000000,
        0x94000000, 0x00000000, 0x98000000, 0x00000000, 0x9c000000, 0x00000000,
        0xa0000000, 0x00000000, 0xa4000000, 0x00000000, 0xa8000000, 0x00000000,
        0xac000000, 0x00000000, 0xb0000000, 0x00000000, 0xb4000000, 0x00000000,
        0xb8000000, 0x00000000, 0xbC000000, 0x00000000, 0x534b4c43, 0x80000000,
        0x00000000, 0x00000000, 0x00000100, 0x00000100, 0x00010220, 0x01010005,
        0x00000000, 0x03000008, 0x08000008, 0x06000008, 0x0f000008, 0x78000000,
        0x00000000, 0x01000000, 0x01010004, 0x00000000, 0x02000008, 0x06000008,
        0x05000008, 0x0c000008, 0x60000000, 0x01000000, 0x03000100, 0x01000100,
        0x00000100, 0x00000100, 0x00000000, 0x00000000, 0x00000000, 0x40787d01,
        0x49524550, 0x14000000, 0x00000000, 0x00000000, 0x40000000, 0x4d524453,
        0x14000000, 0x00000000, 0x00000000, 0x00000000
};
#endif

#define HARDCODED_HANDOFF_DATA_SIZE	(sizeof(hardcoded_handoff_data) / sizeof(u32))

void board_init_f(ulong dummy)
{
	int ret;
	struct udevice *dev;

	ret = spl_early_init();
	if (ret)
		hang();

	socfpga_get_managers_addr();

#ifdef USE_HARDCODED_HANDOFF
	/* Write hardcoded handoff value into OCRAM handoff area */
	u32 i;

	for(i = 0; i < HARDCODED_HANDOFF_DATA_SIZE; i++)
		writel(hardcoded_handoff_data[i],
		       (u32 *)SOC64_HANDOFF_BASE + i);
#endif

	sysmgr_pinmux_init();

	if (!(IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) ||
	      IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU))) {
		/* Ensure watchdog is paused when debugging is happening */
		writel(SYSMGR_WDDBG_PAUSE_ALL_CPU,
		       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_WDDBG);
	}

	timer_init();

	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
	if (ret) {
		debug("Clock init failed: %d\n", ret);
		hang();
	}

	if (!(IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) ||
	      IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU))) {
		/*
		 * Enable watchdog as early as possible before initializing other
		 * component. Watchdog need to be enabled after clock driver because
		 * it will retrieve the clock frequency from clock driver.
		 */
		if (CONFIG_IS_ENABLED(WDT))
			initr_watchdog();
	}

	preloader_console_init();
	print_reset_info();
	cm_print_clock_quick_summary();

	ret = uclass_get_device_by_name(UCLASS_NOP, "socfpga-secreg", &dev);
	if (ret) {
		printf("Firewall & secure settings init failed: %d\n", ret);
		hang();
	}

#if CONFIG_IS_ENABLED(ALTERA_SDRAM)
	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
	if (ret) {
		debug("DRAM init failed: %d\n", ret);
		hang();
	}
#endif

#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS)
	mbox_init();

#ifdef CONFIG_CADENCE_QSPI
	mbox_qspi_open();
#endif
#endif

#if !(IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) || IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU))

	ret = uclass_get_device(UCLASS_CACHE, 0, &dev);
	if (ret) {
		debug("CCU init failed: %d\n", ret);
		hang();
	}

#endif /* CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS */
}
